package gpio

import (
	"errors"
	"fmt"
	"os"
)

// gpio驱动
const (
	sYSFS_GPIO_DIR         = "/sys/class/gpio"
	sYSFS_GPIOEXPORT_DIR   = sYSFS_GPIO_DIR + "/export"
	sYSFS_GPIOUNEXPORT_DIR = sYSFS_GPIO_DIR + "/unexport"
	IN                     = "in"
	OUT                    = "out"
)

//in {19, 17, 18, 16, 200, 216, 51, 50}
//out {15, 13, 14, 12, 78, 77, 76, 79}

func Export(gpio int) error {

	file, err := os.OpenFile(sYSFS_GPIOEXPORT_DIR, os.O_WRONLY, 0)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.WriteString(fmt.Sprintf("%d", gpio))
	if err != nil {
		return err
	}
	return nil
}

func UnExport(gpio int) error {

	file, err := os.OpenFile(sYSFS_GPIOUNEXPORT_DIR, os.O_WRONLY, 0)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.WriteString(fmt.Sprintf("%d", gpio))
	if err != nil {
		return err
	}
	return nil
}

func SetDirection(gpio interface{}, direction string) error {

	if gpio_int, ok := gpio.(int); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/gpio%d/direction", sYSFS_GPIO_DIR, gpio_int), os.O_WRONLY, 0)
		if err != nil {
			return err
		}
		defer file.Close()

		_, err = file.WriteString(direction)

		if err != nil {
			return err
		}
		return nil
	} else if gpio_string, ok := gpio.(string); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/%s/direction", sYSFS_GPIO_DIR, gpio_string), os.O_WRONLY, 0)
		if err != nil {
			return err
		}
		defer file.Close()

		_, err = file.WriteString(direction)

		if err != nil {
			return err
		}
		return nil
	}
	return errors.New("please check input")
}

func SetValue(gpio interface{}, value int) error {
	if gpio_int, ok := gpio.(int); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/gpio%d/value", sYSFS_GPIO_DIR, gpio_int), os.O_WRONLY, 0)
		if err != nil {
			return err
		}
		defer file.Close()

		if value > 0 {
			_, err = file.WriteString("1")
		} else {
			_, err = file.WriteString("0")
		}
		if err != nil {
			return err
		}
		return nil
	} else if gpio_string, ok := gpio.(string); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/%s/value", sYSFS_GPIO_DIR, gpio_string), os.O_WRONLY, 0)
		if err != nil {
			return err
		}
		defer file.Close()

		if value > 0 {
			_, err = file.WriteString("1")
		} else {
			_, err = file.WriteString("0")
		}
		if err != nil {
			return err
		}
		return nil
	}
	return errors.New("please check input")
}

func GetValue(gpio interface{}) (int, error) {

	if gpio_int, ok := gpio.(int); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/gpio%d/value", sYSFS_GPIO_DIR, gpio_int), os.O_RDONLY, 0)
		if err != nil {
			return 0, err
		}
		defer file.Close()
		var ch [1]byte
		_, err = file.Read(ch[0:])
		if err != nil {
			return 0, err
		}
		if string(ch[0]) != "0" {
			return 1, nil
		}
		return 0, nil
	} else if gpio_string, ok := gpio.(string); ok {
		file, err := os.OpenFile(fmt.Sprintf("%s/%s/value", sYSFS_GPIO_DIR, gpio_string), os.O_RDONLY, 0)
		if err != nil {
			return 0, err
		}
		defer file.Close()
		var ch [1]byte
		_, err = file.Read(ch[0:])
		if err != nil {
			return 0, err
		}
		if string(ch[0]) != "0" {
			return 1, nil
		}
		return 0, nil
	}
	return -1, errors.New("please check input")
}
